const { Service } = require('egg')
const { tableToList } = require('../utils/tools')

/**
 * * 处理成绩中缺失的属性
 * @param {JSON} data
 * @param {Number} i data中的索引
 * @param {String} newProp 新属性名
 * @param {String} refProp 前参考属性名
 * @param {String} defaultValue 默认值
 * @return {JSON} *
 */
function addUndefinedProperty(data, i, newProp, refProp, defaultValue = ' ') {
  if (data[i][newProp] === undefined) {
    const keys = Object.keys(data[i])
    const insertIndex = keys.findIndex((key) => key === refProp) + 1
    if (insertIndex === -1 || insertIndex > keys.length) {
      keys.push(newProp)
    } else {
      keys.splice(insertIndex, 0, newProp)
    }

    // 使用扩展运算符复制现有属性，并添加新属性
    data[i] = {
      ...data[i],
      [newProp]: defaultValue,
    }

    // 重新排序对象的属性
    data[i] = keys.reduce((obj, key) => ({
      ...obj,
      [key]: data[i][key] || (key === newProp ? defaultValue : ' '),
    }), {})
  }
}

/**
   * * 交换数组中两个元素的位置
   * @param {Array} arr 数组
   * @param {Array} indices 要交换的索引对，例如 [[0, 1], [2, 3]]
   * @return {Array} *
   */
function swapIndices(arr, indices) {
  const swapped = arr.slice() // 创建一个副本，避免直接修改原数组
  indices.forEach(([from, to]) => {
    const temp = swapped[from]
    swapped[from] = swapped[to]
    swapped[to] = temp
  })
  return swapped
}
module.exports = class GradeService extends Service {
  /**
   * * 课程成绩查询
   * @param {String} term 学期
   * @return {Array} *
   */
  async table(term = '') {
    // eslint-disable-next-line no-unused-vars, prefer-const, @typescript-eslint/no-unused-vars
    let [xnm, _, xqm] = term ? term.split('-') : ['', '', '']
    if (term) { xqm = xqm === '1' ? '3' : '12' }
    const Cookie = this.ctx.state.Cookie
    const apiUrl = `${this.ctx.state.baseUrl}/jwglxt/cjcx/cjcx_cxXsgrcj.html?doType=query&gnmkdm=N305005`
    const res = await this.ctx.curl(apiUrl, {
      method: 'POST',
      data: {
        xnm,
        xqm,
        kcbj: '',
        _search: 'false',
        nd: new Date().getTime(),
        'queryModel.showCount': '150',
        'queryModel.currentPage': '1',
        'queryModel.sortName': '',
        'queryModel.sortOrder': 'asc',
        time: `${Math.floor(Math.random() * (10)) + 1}`,
      },
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
        Host: 'jw.hieu.edu.cn',
        Origin: 'http://jw.hieu.edu.cn',
      },
      timeout: 5000,
    })
    if (res.status === 200) {
      try {
        const tableList = JSON.parse(res.data.toString())
        console.log('tableList', tableList)
        for (const key in tableList) {
          if (key !== 'items') {
            delete tableList[key]
          }
        }

        // 开始处理
        const data = tableList.items
        if (data === undefined || data.length === 0) {
          return { table: {}, header: [] }
        }
        for (const i in data) {
          for (const key in data[i]) { // 删掉多余信息
            if (key !== 'bfzcj' & key !== 'xf' & key !== 'kcmc' & key !== 'kcxzmc' & key !== 'jd'
            & key !== 'xnmmc' & key !== 'xqmmc' & key !== 'kclbmc' & key !== 'cjbz') {
              delete data[i][key]
            }
            if (key === 'bfzcj') {
              const v = data[i][key]
              data[i][key] = { score: v }
            }
          }
          if (data[i].cjbz === undefined) { // 添加成绩备注和课程类别
            addUndefinedProperty(data, i, 'cjbz', 'bfzcj')
          }
          if (data[i].kclbmc === undefined) {
            addUndefinedProperty(data, i, 'kclbmc', 'jd')
          }
        }

        const xq = []// 构造存储学期的数组
        const dataxq = JSON.parse(JSON.stringify(data))
        const dataUp = [['']]
        let xqmc = ''
        if (Array.isArray(data) && data.length > 0 && typeof data[0] === 'object'
        && Object.prototype.hasOwnProperty.call(data[0], 'xnmmc') && Object.prototype.hasOwnProperty.call(data[0], 'xqmmc')) {
          xqmc = `${data[0].xnmmc}-${data[0].xqmmc}`
          xq.push(xqmc)
        }
        for (let i = 1; i < data.length; i++) {
          if (data[i].xnmmc !== data[i - 1].xnmmc || data[i].xqmmc !== data[i - 1].xqmmc) {
            dataUp.push(new Array(''))
          }
        }
        for (let i = 1; i < dataxq.length; i++) { // 构造存储学期的数组
          if (data[i].xnmmc !== data[i - 1].xnmmc || data[i].xqmmc !== data[i - 1].xqmmc) {
            xqmc = `${data[i].xnmmc}-${data[i].xqmmc}`
            xq.push(xqmc)
          }
        }
        // 定义要交换的索引对
        const swapPairs = [
          [0, 4],
          [1, 3],
          [2, 6],
          [3, 4], // 注意：最后一个交换与之前的交换重叠，确保逻辑正确
        ]
        for (let i = 0; i < data.length; i++) {
          const dataList = Object.values(data[i]) // 直接获取所有值
          const xqmc2 = `${data[i].xnmmc}-${data[i].xqmmc}`
          const swappedDataList = swapIndices(dataList, swapPairs)// 交换元素位置
          swappedDataList.splice(7, 2)// 移除特定位置的元素
          let kIndex = xq.findIndex((qk) => qk === xqmc2)// 查找或添加新的 k 值
          if (kIndex === -1) {
            kIndex = xq.length
            xq.push(xqmc2)
            dataUp[kIndex] = [] // 初始化新的数组在 dataUp 中
          }
          // 将处理后的数据添加到 dataUp 中
          dataUp[kIndex].push(swappedDataList)
        }

        for (const i of dataUp) { // 删除学期信息
          if (Array.isArray(i)) {
            i.splice(0, 1)
            if (i.length > 0 && i[0] !== undefined && i[0].length === 1) {
              i.splice(0, 1)
            }
          }
        }
        const dataJson = {}
        for (let i = 0; i < xq.length; i++) {
          dataJson[xq[i]] = dataUp[i]
        }
        // 处理结束
        const header = ['名称', '类型', '学分', '成绩', '备注', '课程性质', '绩点']
        return { table: dataJson, header }
      } catch (err) {
        console.log('err', err)
        throw err
      }
    }
    return { table: {}, header: [] }
  }

  /**
   * * 成绩占比数据请求
   * @param {string} link 占比详情请求地址
   * @return {Object} *
   */
  async proportion(link) {
    const Cookie = this.ctx.state.Cookie
    const apiUrl = encodeURI(link)
    const res = await this.ctx.curl(apiUrl, {
      method: 'GET',
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    })
    if (res.status === 200) {
      try {
        const tableList = tableToList(res.data.toString(), '#dataList')
        return tableList
      } catch (err) {
        console.log('err', err)
        throw err
      }
    }
    return {}
  }
}
